package com.gitee.huanminabc.jcommon.model;

import com.gitee.huanminabc.jcommon.base.Assert;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;

/**
 * 费率计算
 * 比如计算费率收取5个点的手续费，实际存储数据库为5或者0.5, 但是在FeeRate的value中都会转换为存储为0.05主要便于计算
 * 规则: 如果>=1那么就会小数点向左移动2位,如果小于1那么就不变
 * 建议: 数据库中存储>=1的值比如5 别存储为0.05 ,当然也兼容小数
 *
 * @Date 2025/05/16
 */
@Slf4j
public class FeeRate extends Number implements Serializable, Comparable<FeeRate> {
    private static final long serialVersionUID = 1L;
    @Getter
    private final BigDecimal value;
    @Getter
    private final Double percentageValue;

    private FeeRate(BigDecimal inValue) {
        Assert.notNull(inValue, FeeRate.class.getSimpleName() + "：入参不能为null");
        Assert.isTrue(inValue.doubleValue() >= 0, "费率不能为负数，实际值=" + inValue);
        //如果是如果大于1那么需要转换为小数
        if (inValue.compareTo(BigDecimal.ONE) < 0) {
            this.value = inValue;
            this.percentageValue = inValue.movePointLeft(2).doubleValue();
        } else {
            this.value = inValue.movePointLeft(2);
            this.percentageValue = this.value.doubleValue();
        }
    }


    public static FeeRate of(BigDecimal value) {
        return new FeeRate(value);
    }

    public static FeeRate of(double value) {
        return of(BigDecimal.valueOf(value));
    }

    /**
     * 计算手续费，四舍五入保留2位小数
     */
    public Money multiply(Money amount) {
        return multiply(amount, RoundingMode.HALF_UP);
    }

    /**
     * 计算手续费，按指定的RoundingMode来保留2位小数
     */
    public Money multiply(Money money, RoundingMode roundingMode) {
        return money.multiply(value, roundingMode);
    }

    /**
     * + 运算
     */
    public FeeRate add(FeeRate other) {
        Assert.notNull(other, "other is null");
        return of(this.value.add(other.value));
    }

    /**
     * - 运算
     */
    public FeeRate subtract(FeeRate other) {
        Assert.notNull(other, "other is null");
        return of(this.value.subtract(other.value));
    }


    //1-费率
    public FeeRate oneMinus() {
        BigDecimal subtract = BigDecimal.ONE.subtract(this.value);
        return of(subtract);
    }


    @Override
    public String toString() {
        return String.format("%s%%", percentageValue);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        FeeRate feeRate = (FeeRate) obj;
        return Objects.equals(value, feeRate.value);
    }

    @Override
    public int hashCode() {
        return Objects.hash(value);
    }

    @Override
    public int compareTo(FeeRate obj) {
        return value.compareTo(obj.value);
    }

    //不允许使用因为转换为int会丢失小数
    @Override
    public int intValue() {
        throw new UnsupportedOperationException(" intValue() not supported for FeeRate");
    }

    //不允许使用因为转换为long会丢失小数
    @Override
    public long longValue() {
        throw new UnsupportedOperationException(" longValue() not supported for FeeRate");
    }

    //返回的是百分比
    @Override
    public float floatValue() {
        return percentageValue.floatValue();
    }

    //返回的是百分比
    @Override
    public double doubleValue() {
        return percentageValue;
    }

    public static void main(String[] args) {
//        FeeRate feeRate = FeeRate.of(0.05);
        FeeRate feeRate = FeeRate.of(10);
        System.out.println(feeRate.doubleValue());
        System.out.println(feeRate.getPercentageValue());
        System.out.println(feeRate.multiply(Money.of(100)));
        System.out.println(feeRate.multiply(Money.of(100), RoundingMode.HALF_UP));
        System.out.println(feeRate.add(FeeRate.of(0.02)));
        System.out.println(feeRate.subtract(FeeRate.of(0.02)));
        System.out.println(feeRate.oneMinus().multiply(Money.of(100)));
    }

}
